//折线图
interface ChartData  {
  // 横纵坐标配置
  config:{ x:string[], y:number[] };
  // 数据
  data:number[];

  // 坐标线上的刻度大小（由程度根据画布和配置计算生成）
  offset:{
    x:number, //x横坐标一个刻度大小
    y:number, //y纵坐标一个刻度大小
    scaleY:number,//y纵坐标标尺与实际画布尺寸的缩放比例
  };
}

let cdata:ChartData = {
  config:{
    x:['1月','2月','3月','4月','5月','6月','7月'],
    y:[50,100,150,200,250,300,350,400]
  }, 
  data:[153,265,143,112,288,312,245],
  offset:{x:0, y:0, scaleY:1},

}



// 折线图
class Zhexiantu {

  // 用户配置表数据：见ChartData
  private data:ChartData;

  // 画布和上下文
  // private canvas:HTMLCanvasElement;
  private ctx:CanvasRenderingContext2D;

  // 图片配置数据
  padding:number = 80;// 画布边距：
  wh:{w:number, h:number};//去除画布边距后的 宽和高

  // 构造函数
  constructor(mycavSlt:string, data:ChartData){

    this.data = data;

    let canvas = document.querySelector(mycavSlt) as HTMLCanvasElement;
    this.ctx = canvas.getContext("2d") as CanvasRenderingContext2D;

    // 画布宽和高
    this.wh={
      w:canvas.clientWidth-this.padding,
      h:canvas.clientHeight-this.padding,
    }

    // 重置画布的原点坐标(xy交叉点为原点)
    this.ctx.translate(this.padding, this.wh.h);
    this.ctx.save();
  }

  // 创建图表
  public create(){
    this.setLayout();
    this.setPoint();
    this.setChartInfo();
  }

  // 图表基础布局
  private setLayout(){
    let ctx = this.ctx;
    let config =  this.data.config;

    // 坐标线宽和高度(坐标轴和坐标线均使用此尺寸)
    let wh={w:this.wh.w-this.padding, h:this.wh.h-this.padding}

  
    // 画数据区域：坐标轴 和 背景色
    ctx.save();
    ctx.fillStyle = "#ffff0030";
    ctx.strokeStyle = "#555"; 
    ctx.lineWidth = 2;
    ctx.rect(0, 0, wh.w, -wh.h);//一次性画出坐标区域
    ctx.stroke();
    ctx.fill();
    ctx.restore();

    /* 
     * 画刻度
     * x轴刻度：一个刻度宽度 = 总宽度/刻度个数
     * y轴刻度：一个刻度高度 = 总高度/刻度个数
     * 说明：x轴刻度大小不影响数字，但y轴的刻度是和数值大小相关的（即y轴的数值有缩放）。
     * 一个刻度的像素高度 : 显示的刻度值 = 实际值大小 : 缩放值大小
     */
    this.data.offset.x=(wh.w-50)/config.x.length;//x轴一个刻度尺寸
    this.data.offset.y=(wh.h-50)/config.y.length;//y轴一个刻度尺寸
    this.data.offset.scaleY = config.y[0]/this.data.offset.y;//缩放比例
    // console.log(config.y[0], this.data.offset.y);
    
    ctx.save();
    ctx.font = "20px 黑体 ";
    ctx.textAlign = "center";
    ctx.beginPath();

    // 横坐标刻度和刻度线
    for(let i=0; i<config.x.length; i++){
      let x = (i+1)*this.data.offset.x;//x轴最左端为原点
      ctx.moveTo(x, 0);
      // ctx.lineTo(x, -wh.h);
      ctx.lineTo(x, -10);//10px的刻度线高度
      ctx.fillText(config.x[i], x , 25);//刻度值
    }
    ctx.stroke();
    ctx.closePath();

    // 纵坐标刻度和刻度线
    ctx.beginPath();
    ctx.lineWidth = .5;
    ctx.strokeStyle = "#AAA";
    for(let i=0; i<config.y.length; i++){
      let y = (i+1)*this.data.offset.y;//最下端为原点
      ctx.moveTo(0, -y);
      ctx.lineTo(wh.w, -y);
      ctx.fillText(String(config.y[i]), -25, -y);
    }

    ctx.stroke();
    ctx.closePath();
    ctx.restore();
  }


  // 设置打点，数据值，连线
  setPoint(){
    let ctx = this.ctx;
    let offset = this.data.offset;
    // console.log(offset);

    ctx.save();
    ctx.font="16px 黑体";
    ctx.textAlign="center";

    //1. 打点 并写值
    let i=1;
    for(let v of this.data.data){
      ctx.beginPath();
      ctx.arc(i*offset.x, -v/offset.scaleY, 5, 0, 2*Math.PI);
      ctx.fillStyle = "blue";
      ctx.fill();

      ctx.fillText(String(v), i*offset.x, -v/offset.scaleY-20);
      i++;
    }

    //2. 连线
    i=1;
    ctx.beginPath();
    for(let v of this.data.data){
      ctx.lineTo(i*offset.x, -v/offset.scaleY);
      i++;
    }
    ctx.stroke();

    ctx.restore();
  }



  // 设置图表信息
  public setChartInfo(title:string='Canvas折线图案例展示'){
    let ctx = this.ctx;
    let base = {w:this.wh.w-this.padding, h:this.wh.h}

    ctx.save();
    ctx.textAlign = "center";
    ctx.font = "20px 黑体";
    ctx.fillText(title, base.w/2, -base.h+40);
    ctx.restore();
  }


}





(new Zhexiantu('#mycav', cdata)).create();


